import { Doc } from 'yjs';
import { isEmpty, pick, omit } from 'lodash-es';
import { logger } from '../logger.js';
import request from '../request.js';
import { AxiosError } from 'axios';

type ReviewComment = {
  reviewCommentList: any[];
};

type ChangedReview = {
  changeReviewComment: any;
  type: string;
};

// 使用 ReturnType 计算 toJSON 方法的返回类型
type DocJson = ReturnType<Doc['toJSON']>;

// 获取评审意见的payload
function getReviewCommentPayload({ reviewCommentList, changeReviewComment, type }) {
  const adjustedReviewCommentList = [];
  const addedReviewCommentList = [];
  const removedReviewCommentList = [];

  if (type === 'delete') {
    removedReviewCommentList.push(changeReviewComment);
  }
  if (!type && !isEmpty(changeReviewComment)) {
    if (reviewCommentList.some((i) => i.uuid === changeReviewComment.uuid)) {
      adjustedReviewCommentList.push(changeReviewComment);
    }
    if (reviewCommentList.every((i) => i.uuid !== changeReviewComment.uuid)) {
      addedReviewCommentList.push(omit(changeReviewComment, ['attachmentList', 'commentPicList']));
    }
  }

  return { adjustedReviewCommentList, addedReviewCommentList, removedReviewCommentList };
}

const transformer = (document: Doc, reviewChangeQueue): DocJson => {
  const reviewConfig = document.getMap('reviewConfig').get('data');
  const reviewContent = document.getMap('reviewContent').get('data');
  const reviewComment = document.getMap('reviewComment').get('data') as ReviewComment;
  const reviewPrepareTime = document.getMap('reviewPrepareTime').get('data');
  const noReviewComment = document.getMap('noReviewComment').get('data');

  let changeReviewComment = {};
  let type = '';
  if (reviewChangeQueue && !!reviewChangeQueue.get(0)) {
    changeReviewComment = (reviewChangeQueue.get(0) as ChangedReview).changeReviewComment;
    type = (reviewChangeQueue.get(0) as ChangedReview).type;
    reviewChangeQueue.delete(0);
  }

  // 获取评审意见参数
  const { adjustedReviewCommentList, addedReviewCommentList, removedReviewCommentList } = getReviewCommentPayload({
    changeReviewComment,
    reviewCommentList: reviewComment.reviewCommentList,
    type,
  });

  const payload = {
    ...pick(reviewConfig, [
      'authorList',
      'criticalReviewerList',
      'reviewerList',
      'moderator',
      'reviewType',
      'reviewTime',
      'reviewLocation',
      'planFinishTime',
      'templateId',
      'templateName',
      'templateVersion',
      'reviewName',
    ]),
    ...pick(reviewContent, ['reviewContentHeaders', 'reviewContentRowValues']),
    ...pick(noReviewComment, ['noCommentsCriticalReviewerList']),
    ...pick(reviewPrepareTime, ['prepareTimeList']),
    adjustedReviewCommentList,
    addedReviewCommentList,
    removedReviewCommentList,
  };
  return {
    payload,
    current: { changeReviewComment, type },
  };
};

const saveSuccess = (document: Doc, { changeReviewComment, type }) => {
  // 接口返回成功后，将changeReviewComment处理到reviewCommentList中并清空队列中的changeReviewComment
  const reviewComment = document.getMap('reviewComment').get('data') as ReviewComment;
  const { reviewCommentList } = reviewComment;
  // 删
  if (type && type === 'delete') {
    const newReviewCommentList = reviewCommentList.filter((i) => i.uuid !== changeReviewComment.uuid);
    document.getMap('reviewComment').set('data', { reviewCommentList: newReviewCommentList });
  }
  if (!type && !isEmpty(changeReviewComment)) {
    // 改
    if (reviewCommentList.some((i) => i.uuid === changeReviewComment.uuid)) {
      const index = reviewCommentList.findIndex((i) => i.uuid === changeReviewComment.uuid);
      const updatedReviewCommentList = reviewCommentList.map((item, idx) =>
        idx === index ? changeReviewComment : item,
      );
      document.getMap('reviewComment').set('data', { reviewCommentList: updatedReviewCommentList });
    }
    // 增
    if (reviewCommentList.every((i) => i.uuid !== changeReviewComment.uuid)) {
      const commentList = [...reviewCommentList];
      commentList.unshift(changeReviewComment);
      document.getMap('reviewComment').set('data', { reviewCommentList: commentList });
    }
  }
};

const updateReviewService = {
  save: async (data, reviewChangeQueue = undefined) => {
    const currentReviewStatus = data.document.getMap('currentReviewStatus').get('data') ;
    if( currentReviewStatus.reviewStatus !== '评审中' && currentReviewStatus.reviewStatus !== '预评审中' ){
      logger.info("🚀 ~ save: ~ webhookUrl:", currentReviewStatus.reviewStatus)
      return
    }
    let dataset = transformer(data.document, reviewChangeQueue);
    if (!data.documentName.includes('.')) {
      logger.error('documentName is invalid before requesting', data.documentName);
      return;
    }
    const documentNameArr = data.documentName.split('.');
    if (documentNameArr.length !== 2) {
      logger.error('documentName is invalid before requesting', data.documentName);
      return;
    }
    const reviewInternalKey = documentNameArr[1];
    const isServiceChangeDocument = data.document.getMap('serviceFlag').get('data');
    if (isServiceChangeDocument) {
      return;
    }
    const webhookUrl = process.env.WEBHOOK_URL_POST.replace('{review_internal_key}', reviewInternalKey);
    let response;
    try {
      logger.debug(`save dataset:`, dataset.payload);
      response = await request.post(webhookUrl, dataset.payload);
      logger.info(`${data.reason} = save response:`, response.data);
    } catch (e) {
      if ((e as AxiosError).response) {
        logger.info(`request before error: ${JSON.stringify((e as AxiosError).config?.data)}`);
        logger.error(`response error: ${JSON.stringify((e as AxiosError).response?.data)}`);
      }
      logger.error(`save Caught error in extension-webhook: ${e}`);
      // 需要处理异常、防止接口与redis不可用时的异常处理，并返回给客户端，及时通知到客户，避免数据丢失
      data.document.broadcastStateless(
        JSON.stringify({
          type: 'serviceError',
          code: 500,
          message: '服务异常，数据未保存成功，请稍候重试',
          success: false,
          detail: {
            requestData: (e as AxiosError).config?.data,
            responseData: (e as AxiosError).response?.data,
          },
        }),
      );
    }
    if (response) {
      saveSuccess(data.document, dataset.current);
      data.document.broadcastStateless(JSON.stringify(response.data));
    }
  },
};

export default updateReviewService;
